defmodule IocpMonitor.Worker.DeviceAddressHolder do
  require Logger

  use GenServer

  alias IocpMonitor.Sender
  alias IocpMonitor.Worker.Receiver
  alias IocpMonitor.DeviceAddressHolders

  def start_link({client, sup}) do
    # Agent.start_link(fn -> {client, sup, fetch_device_address(client)} end, name: {:via, Registry, {DeviceAddressHolders, sup}})
    GenServer.start_link(__MODULE__, {client, sup}, name: {:via, Registry, {DeviceAddressHolders, sup}})
  end

  def get(agent) do
    # Agent.get_and_update(agent, fn
    #   {client, sup, nil} ->
    #     device_address = fetch_device_address(client)
    #     {device_address, {client, sup, device_address}}
    #   {client, sup, device_address} ->
    #     {device_address, {client, sup, device_address}}
    # end)
    GenServer.call(agent, :get)
  end

  defp fetch_device_address(client) do
    :ok = Sender.device_address!(client)
    Receiver.receive_device_address(client)
  end

  @impl true
  def init({client, sup}) do
    {:ok, {client, sup, nil}}
  end

  @impl true
  def handle_call(:get, from, {client, sup, nil}) do
    handle_call(:get, from, {client, sup, fetch_device_address(client)})
  end

  def handle_call(:get, _from, {_client, _sup, device_address} = state) do
    {:reply, device_address, state}
  end

  @impl true
  def terminate(reason, {client, sup, _}) do
    :gen_tcp.close(client)
    IocpMonitor.Client.Supervisor.terminate_child(sup)
  end

  @doc false
  def child_spec(arg) do
    %{
      id: __MODULE__,
      start: {__MODULE__, :start_link, [arg]},
      type: :worker,
      restart: :temporary,
      shutdown: 500
    }
  end

end
